#ifndef WALKAWARE_SERVICES_KINECTSERVICE_H
#define WALKAWARE_SERVICES_KINECTSERVICE_H

#include <QTimer>

#include <WalkaWare/Kinect/Device.h>
#include <WalkaWare/Services/SignaledService.h>

namespace WalkaWare
{

namespace Services
{

class KinectService : public SignaledService
{
	Q_OBJECT

	public:

		typedef SignaledService BaseType;
		typedef KinectService   ThisType;

		KinectService(void)
		{
			this->connect(&(this->rgbTimer),   SIGNAL(timeout()),  SLOT(acquireRgb()));
			this->connect(&(this->depthTimer), SIGNAL(timeout()),  SLOT(acquireDepth()));
			this->connect(&(this->accelTimer), SIGNAL(timeout()),  SLOT(acquireAcceleration()));

			this->rgbTimer.setInterval(40);
			this->depthTimer.setInterval(40);
			this->accelTimer.setInterval(40);
		}

		virtual ~KinectService(void)
		{
			this->quit();
		}

		void setDeviceIndex(int index)
		{
			const bool running = this->isRunning();
			if (running)
			{
				this->blockSignals(true);
				this->quit();
			}

			this->device.setDeviceIndex(index);

			if (running)
			{
				this->start();
				this->blockSignals(false);
			}
		}

		int deviceIndex(void) const
		{
			return this->device.deviceIndex();
		}

		void setAcquireRgbInterval(int msec)
		{
			this->rgbTimer.setInterval(msec);
		}

		int acquireRgbInterval(void) const
		{
			return this->rgbTimer.interval();
		}

		void setAcquireDepthInterval(int msec)
		{
			this->depthTimer.setInterval(msec);
		}

		int acquireDepthInterval(void) const
		{
			return this->depthTimer.interval();
		}

		void setAcquireAccelerationInterval(int msec)
		{
			this->accelTimer.setInterval(msec);
		}

		int acquireAccelerationInterval(void) const
		{
			return this->accelTimer.interval();
		}

	signals:

		void imageReady        (QImage image, quint32 timestamp);
		void depthReady        (WalkaWare::Shared::RawDepthMap depthMap, quint32 timestamp);
		void accelerationReady (float x, float y, float z, quint32 timestamp);

	public slots:

		virtual void start(void)
		{
			if (this->isRunning()) return;

			BaseType::start();

			//this->rgbTimer.start();
			this->depthTimer.start();
			this->accelTimer.start();
		}

		virtual void quit(void)
		{
			if (!this->isRunning()) return;

			this->rgbTimer.stop();
			this->depthTimer.stop();
			this->accelTimer.stop();

			BaseType::quit();

			freenect_sync_stop();
		}

	protected slots:

		void acquireRgb(void)
		{
			if (!this->isRunning()) return;

			QImage  image;
			quint32 timestamp = 0;
			if (!this->device.acquireRgb(image, timestamp)) return;

			emit imageReady(image, timestamp);
		}

		void acquireDepth(void)
		{
			if (!this->isRunning()) return;

			Shared::RawDepthMap depthMap;
			quint32             timestamp = 0;
			if (!this->device.acquireDepth(depthMap, timestamp)) return;

			emit depthReady(depthMap, timestamp);
		}

		void acquireAcceleration(void)
		{
			if (!this->isRunning()) return;

			Shared::Vec3f acc;
			quint32       timestamp = 0;
			if (!this->device.acquireAcceleration(acc, timestamp)) return;

			emit accelerationReady(acc[0], acc[1], acc[2], timestamp);
		}

	protected:

		Kinect::Device device;
		QTimer         rgbTimer;
		QTimer         depthTimer;
		QTimer         accelTimer;

	private:

		Q_DISABLE_COPY(KinectService)
};

} // end namespace Services

} // end namespace WalkaWare

#endif // WALKAWARE_SERVICES_KINECTSERVICE_H
